#include "grflib_stdafx.h"
#include <DXUTcamera.h>
#include "../include/Camera.h"
#include "../include/ImgMath.h"

namespace grflib { namespace engine { namespace core {

CCamera::CCamera(int motionType)
	: m_motionType(motionType),
    m_isInteractive(true),
	m_fWidthRatio(1.0f),
	m_fHeightRatio(1.0f),
	m_fovy((float)(D3DX_PI) / 4),
	m_fNear(0.1f),
	m_fFar(1000.0f)
{
	if (MOTION_MODELVIEW == m_motionType)
	{
		m_pCamera = new CModelViewerCamera; 
		CModelViewerCamera *pCam = dynamic_cast<CModelViewerCamera *>(m_pCamera);
		pCam->SetRadius(1.0f, 0.1f);
	}
	else if (MOTION_FIRSTPERSON == m_motionType)
	{
		m_pCamera = new CFirstPersonCamera;
	}
	else
		m_pCamera = 0;
}

CCamera::~CCamera()
{
	SAFE_DELETE(m_pCamera);
}

void CCamera::SetFOV(float fovy, float w, float h)
{
    image::math::SaturateIn(m_fWidthRatio, 0.0f, 1.0f);
    image::math::SaturateIn(m_fHeightRatio, 0.0f, 1.0f);
	m_fovy = fovy;
    //if (m_pCamera)
    //    m_pCamera->SetProjParams(m_fovy, m_fWidth / m_fHeight, m_fNear, m_fFar);
}

void CCamera::SetClipPlanes(float fNear, float fFar)
{
	m_fNear = fNear;
	m_fFar = fFar;
    //if (m_pCamera)
    //    m_pCamera->SetProjParams(m_fovy, m_fWidth / m_fHeight, m_fNear, m_fFar);
}

void CCamera::FrameMove(float fElapsedTime)
{ 
    if (m_pCamera && m_isInteractive) m_pCamera->FrameMove(fElapsedTime); 
}

LRESULT CCamera::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if (m_pCamera && m_isInteractive)
		return m_pCamera->HandleMessages(hWnd, uMsg, wParam, lParam);
	else return 0;
}

HRESULT CCamera::OnResize(ID3D10Device *pd3dDevice, IDXGISwapChain *pSwapChain, const DXGI_SURFACE_DESC *pBufferSurfaceDesc)
{
	if (!m_pCamera)
		return S_OK;

	//calculate screen occupancy
	float fAspectRatio = static_cast<float>(pBufferSurfaceDesc->Width) * m_fWidthRatio /
		(static_cast<float>(pBufferSurfaceDesc->Height) * m_fHeightRatio);

	m_pCamera->SetProjParams(m_fovy, fAspectRatio, m_fNear, m_fFar);
	
	if (MOTION_MODELVIEW == m_motionType)
	{
		CModelViewerCamera *pCam = dynamic_cast<CModelViewerCamera *>(m_pCamera);
		assert(pCam);
		pCam->SetWindow((int)((float)pBufferSurfaceDesc->Width * m_fWidthRatio), (int)((float)pBufferSurfaceDesc->Height * m_fHeightRatio));
		pCam->SetButtonMasks(MOUSE_MIDDLE_BUTTON, MOUSE_WHEEL, MOUSE_LEFT_BUTTON);
	}
	else if (MOTION_FIRSTPERSON == m_motionType)
	{
	}

	return S_OK;
}

HRESULT CCamera::OnResize(UINT width, UINT height)
{
    if (!m_pCamera)
        return S_OK;
    float fAspectRatio = (width * m_fWidthRatio) / (height * m_fHeightRatio);
    m_pCamera->SetProjParams(m_fovy, fAspectRatio, m_fNear, m_fFar);
    return S_OK;
}

}}} //namespaces